<?php
///////////////////////////////////////////////////////////////////////////////
/*
node.php

Class Node - class containing methods for retrieving and saving node data.


*/

class Node {

    private $id;
    private $parentnode_id;
    private $leveltype_id;
    private $name;
    private $description;
    private $webaddress;
    public static $TABLE_NODE = TABLE_NODE;


    /////////////////////////////////////////////////////////////////////////////
    // contructor - instantiates node object with supplied attributes
    public function __construct($id = null, $parentnode_id = null, $leveltype_id = null, $name = null,
                         $description = null, $webaddress = null) {
        $this->init($id, $parentnode_id, $leveltype_id, $name, $description, $webaddress);
    }


    /////////////////////////////////////////////////////////////////////////////
    // init - convenience function to set all node attribute values at once
    public function init($id, $parentnode_id, $leveltype_id, $name, $description, $webaddress) {
        $this->setID($id);
        $this->setParentnodeID($parentnode_id);
        $this->setLeveltypeID($leveltype_id);
        $this->setName($name);
        $this->setDescription($description);
        $this->setWebaddress($webaddress);
    }

    /////////////////////////////////////////////////////////////////////////////
    // load - initialize the node by loading it from the database based on the
    // specificed id
    public function load($id) {
        $sql = "SELECT id, name, description, parentnode_id, leveltype_id, webaddress " .
             "FROM " . Node::$TABLE_NODE . " where id = " . $id;
        //$result = DatabaseManager::getInstance()->getDatabaseConnection()->query($sql);
        $result = DatabaseManager::getInstance()->query($sql);
        if ($row = $result->fetch_assoc()) {
            $this->init($row['id'], $row['parentnode_id'], $row['leveltype_id'],
                        $row['name'], $row['description'], $row['webaddress']);
        } else {
            // some error handling?
            return false;
        }
        return true;
    }

    /////////////////////////////////////////////////////////////////////////////
    // insert - insert a new node into the database and return the new Node
    public function insert() {
        $sql = "CALL insertNode({$this->getParentnodeID()}, " .
                               "{$this->getLeveltypeID()}, " .
                               "'{$this->getName()}', " .
                               "'{$this->getDescription()}', " .
                               "'{$this->getWebaddress()}', " .
                               "@newNodeID)";
        //$result = DatabaseManager::getInstance()->getDatabaseConnection()->query($sql);
        $result = DatabaseManager::getInstance()->query($sql);
        $sql = "select @newNodeID";
        //$result = DatabaseManager::getInstance()->getDatabaseConnection()->query($sql);
        $result = DatabaseManager::getInstance()->query($sql);
        if ($row = $result->fetch_assoc()) {
            $this->setID($row["@newNodeID"]);
        } else {
            // some error handling?
            return false;
        }
        return true;
    }

    /////////////////////////////////////////////////////////////////////////////
    // update - update the node to the database (node already exists in database)
    public function update() {
        $sql = "UPDATE " . Node::$TABLE_NODE . " set parentnode_id = {$this->getParentnodeID()}, " .
                                "leveltype_id = {$this->getLeveltypeID()}, " .
                                        "name = '{$this->getName()}', " .
                                 "description = '{$this->getDescription()}', " .
                                  "webaddress = '{$this->getWebaddress()}' " .
               "WHERE id = {$this->getID()}";
        $result = DatabaseManager::getInstance()->query($sql);
    }

    /////////////////////////////////////////////////////////////////////////////
    // delete - delete the node from the database if it has no child nodes or
    // associated leaf references
    public function delete() {
        if ($this->isParent()) {
            return false;
        }
        $sql = "DELETE FROM " . Node::$TABLE_NODE . " WHERE id = {$this->getID()}";
        $result = DatabaseManager::getInstance()->query($sql);
    }

    /////////////////////////////////////////////////////////////////////////////
    // powerDelete - delete the node from the database including child nodes and
    // associated leaf references (very dangerous and powerful)
    // (might need to implement)


    /////////////////////////////////////////////////////////////////////////////
    // isParent - return true if node has at least one child node or at least
    // one child leaf 
    public function isParent() {
      return $this->hasChildNodes() || $this->hasChildLeafs();
    }

    /////////////////////////////////////////////////////////////////////////////
    // hasChildNodes - return true if node has at least one child node
    public function hasChildNodes() {
        return $this->getChildNodeCount() > 0;
    }

    /////////////////////////////////////////////////////////////////////////////
    // hasChildLeafs - return true if node has at least one child leaf
    public function hasChildLeafs () {
        return $this->getChildLeafCount() > 0;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getChildNodeCount - return the number of child nodes under node - get
    // from database
    public function getChildNodeCount() {
        $childNodeCount = 0;
        $sql = "SELECT count(*) as child_node_count FROM " . Node::$TABLE_NODE .
               " where parentnode_id = {$this->getID()}";
        $result = DatabaseManager::getInstance()->query($sql);
        if ($row = $result->fetch_assoc()) {
            $childNodeCount = $row['child_node_count'];
        } else {
            return false;
        }
        return $childNodeCount;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getChildLeafCount - return the number of child leafs under node - get
    // from database
    public function getChildLeafCount() {
        $childLeafCount = 0;
        $sql = "SELECT count(*) as child_leaf_count FROM " . LEAF::$TABLE_LEAF .
               " where parentnode_id = {$this->getID()}";
        $result = DatabaseManager::getInstance()->query($sql);
        if ($row = $result->fetch_assoc()) {
            $childLeafCount = $row['child_leaf_count'];
        } else {
            return false;
        }
        return $childLeafCount;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getID - get the node id
    public function getID() {
        return $this->id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // setID - set the node id
    public function setID($id) {
        $this->id = $id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getParentnodeID - get the parent node id
    public function getParentnodeID() {
        return $this->parentnode_id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // setParentnodeID - set the parent node id
    public function setParentnodeID($parentnode_id) {
        $this->parentnode_id = $parentnode_id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getLeveltypeID - get the level type id
    public function getLeveltypeID() {
        return $this->leveltype_id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // setLeveltypeID - set the level type id
    public function setLeveltypeID($leveltype_id) {
        $this->leveltype_id = $leveltype_id;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getName - get the name
    public function getName() {
        return $this->name;
    }
    /////////////////////////////////////////////////////////////////////////////
    // setName - set the name
    public function setName($name) {
        $this->name = $name;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getDescription - get the description
    public function getDescription() {
        return $this->description;
    }
    /////////////////////////////////////////////////////////////////////////////
    // setDescription - set the description
    public function setDescription($description) {
        $this->description = $description;
    }

    /////////////////////////////////////////////////////////////////////////////
    // getWebaddress - get the web address
    public function getWebaddress() {
        return $this->webaddress;
    }
    /////////////////////////////////////////////////////////////////////////////
    // setWebaddress - set the web address
    public function setWebaddress($webaddress) {
        $this->webaddress = $webaddress;
    }

    /////////////////////////////////////////////////////////////////////////////
    // printNodeData - debug function that dumps node attributes
    public function printNodeData($desc = "") {
        //print("--------------------------------------------\n");
        print("{$desc}:\n");
        print("\tID: {$this->getID()}\n");
        print("\tPARENT ID: {$this->getParentnodeID()}\n");
        print("\tLEVEL ID: {$this->getLeveltypeID()}\n");
        print("\tNAME: {$this->getName()}\n");
        print("\tDESCRIPTION: {$this->getDescription()}\n");
        print("\tWEB ADDRESS: {$this->getWebaddress()}\n");
    }








    // Static functions - mainly for retrieving groups of nodes

    /////////////////////////////////////////////////////////////////////////////
    public static function loadChildNodesOfNode($node) {
        return Node::loadChildNodesOfNodeByID($node->getID());
    }

    /////////////////////////////////////////////////////////////////////////////
    public static function loadChildNodesOfNodeByID($node_id) {
        return Node::loadNodes('parentnode_id = ' . $node_id);
    }

    /////////////////////////////////////////////////////////////////////////////
    public static function loadNodesOfLevelID($level_id) {
        return(Node::loadNodes('leveltype_id = ' . $level_id));
    }


    /////////////////////////////////////////////////////////////////////////////
    public static function loadNodes($condition) {
        $nodes = array();
        $sql = "SELECT id, name, description, parentnode_id, leveltype_id, webaddress FROM " .
               Node::$TABLE_NODE . " where " .
               $condition . " order by upper(name) ";
        $result = DatabaseManager::getInstance()->query($sql);
        while ($row = $result->fetch_assoc()) {
            $node = new Node($row['id'],
                             $row['parentnode_id'],
                             $row['leveltype_id'],
                             $row['name'],
                             $row['description'],
                             $row['webaddress']);
            $nodes[] = $node;
        }
        return $nodes;
    }

    /////////////////////////////////////////////////////////////////////////////
    public static function printNodesData($nodes, $desc = "") {
        print($desc . "\n");
        $i = 0;
        foreach ($nodes as $node) {
            $i++;
            $node->printNodeData("Node " . $i);
        }
        print(count($nodes) . " nodes\n");
    }





}

?>
